#ifndef CONIN_UI_CONTROL_COLLECTION_H
#define CONIN_UI_CONTROL_COLLECTION_H

#include "control.h"
#include "font.h"
#include <string>
#include <map>

namespace cnc {

	namespace ui {
	
		class ControlCollection
		{
		protected:
			const HWND &hwndParent_;
			typedef std::map<std::string, Control *> ControlContainer_;
			ControlContainer_ ctlContainer_;
			typedef std::map<std::string, Font *> FontContainer_;
			FontContainer_ fontContainer_;
		public:
			ControlCollection(HWND &hwndParent) : hwndParent_(hwndParent)
			{
				InitCommonControls();
				RegisterTitleBarControl();
			}
			static HBRUSH onCtlColor(HWND /*hwnd*/, HDC hdc, HWND hwndChild, int type)
			{
				if (type == CTLCOLOR_STATIC) {
					Static label(hwndChild);
					label.color(hdc, type);
					return GetSysColorBrush(COLOR_3DFACE);
				} else {
					Control control(hwndChild);
					control.color(hdc, type);
					return GetSysColorBrush(COLOR_3DFACE);
				}
			}
			Font *addFont(std::string name, LONG pointSize, LPCTSTR lpszFace,
				bool bold = false, bool italic = false)
			{
				Font *font = new Font(pointSize, lpszFace, bold, italic);
				if (font == 0)
					return 0;
				std::pair<std::map<std::string, Font *>::iterator, bool> result
					= fontContainer_.insert(std::pair<std::string, Font *>(name, font));
				if (result.second == false) {
					delete font;
					return result.first->second;
				}
				return fontContainer_[name];
			}
			void removeFonts()
			{
				for (FontContainer_::iterator it = fontContainer_.begin();
					it != fontContainer_.end(); ++it) {
					delete it->second;
				}
				fontContainer_.clear();
			}
			HFONT font(std::string name)
			{
				return fontContainer_[name]->getHandle();
			}
			void removeControls()
			{
				for (ControlContainer_::iterator it = ctlContainer_.begin();
					it != ctlContainer_.end(); ++it) {
					delete it->second;
				}
				ctlContainer_.clear();
			}
		protected:
			Control *addControl_(std::string name, Control *control)
			{
				if (control == 0)
					return 0;
				std::pair<std::map<std::string, Control *>::iterator, bool> result
					= ctlContainer_.insert(std::pair<std::string, Control *>(name, control));
				if (result.second == false) {
					delete control;
					return result.first->second;
				}
				return ctlContainer_[name];
			}
			Control *getControl_(std::string name)
			{
				ControlContainer_::iterator it = ctlContainer_.find(name);
				if (it != ctlContainer_.end())
					return ctlContainer_[name];
				return 0;
			}
		public:
			Control *addControl(std::string name,
				LPCTSTR lpClassName, LPCTSTR lpWindowName,
				DWORD dwStyle, int x, int y, int nWidth, int nHeight,
				int nIDDlgItem, LPVOID lpParam = NULL)
			{
				return addControl_(name,
					new Control(hwndParent_, lpClassName,
					lpWindowName, dwStyle, x, y, nWidth, nHeight,
					nIDDlgItem, lpParam));
			}
			Control *getControl(std::string name)
			{
				return ctlContainer_[name];
			}
			Static *addStatic(std::string name,
				LPCTSTR lpWindowName, int x, int y,
				int nWidth, int nHeight, int nIDDlgItem,
				DWORD dwStyle = 0)
			{
				return static_cast<Static *>(addControl_(name,
					new Static(hwndParent_, lpWindowName, x, y,
					nWidth, nHeight, nIDDlgItem, dwStyle)));
			}
			Button *addButton(std::string name,
				LPCTSTR lpWindowName, int x, int y,
				int nWidth, int nHeight, int nIDDlgItem,
				DWORD dwStyle = BS_PUSHBUTTON)
			{
				return static_cast<Button *>(addControl_(name,
					new Button(hwndParent_, lpWindowName, dwStyle, x, y,
					nWidth, nHeight, nIDDlgItem)));
			}
			PushButton *addPushButton(std::string name,
				LPCTSTR lpWindowName, int x, int y,
				int nWidth, int nHeight, int nIDDlgItem,
				DWORD dwStyle = 0)
			{
				return static_cast<PushButton *>(addControl_(name,
					new PushButton(hwndParent_, lpWindowName, x, y,
					nWidth, nHeight, nIDDlgItem, dwStyle)));
			}
			GroupBox *addGroupBox(std::string name,
				LPCTSTR lpWindowName, int x, int y,
				int nWidth, int nHeight)
			{
				return static_cast<GroupBox *>(addControl_(name,
					new GroupBox(hwndParent_, lpWindowName, x, y,
					nWidth, nHeight)));
			}
			Trackbar *addTrackbar(std::string name,
				int x, int y, int nWidth, int nHeight,
				int nIDDlgItem, DWORD dwStyle)
			{
				return static_cast<Trackbar *>(addControl_(name,
					new Trackbar(hwndParent_, x, y, nWidth, nHeight,
					nIDDlgItem, dwStyle)));
			}
		};
		
	} // namespace ui
	
} // namespace cnc

#endif
